// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: shared_lib_win32.hpp 229 2008-09-15 13:39:09Z heavyzheng $
//

#ifndef ZZHENG_UTILITY_SHARED_LIB_WIN32_HPP_20080828__
#define ZZHENG_UTILITY_SHARED_LIB_WIN32_HPP_20080828__

#include <zzheng/config.hpp>
#include <boost/noncopyable.hpp>
#include <windows.h>
#include <string>

#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace zzheng {
namespace sys {
namespace detail {

    //! This class wraps a shared library on the win32 platform.
    class shared_lib_wrapper: private boost::noncopyable {

    public:

        //! Constructs a shared library wrapper. The shared library will NOT be loaded on
        //! construction. It will be loaded when it is used for the first time.
        //! \param path       the path to the shared library.
        //! \param auto_free  whether to free the shared library on destruction.
        explicit shared_lib_wrapper(const std::string& path, bool auto_free)
        : handle_(0), path_(path), auto_free_(auto_free), failed_(false) {
            // Do nothing.
        }

        //! Destructor. If the shared library has been loaded, and auto_free flag is set to true,
        //! this destructor will free the shared library.
        ~shared_lib_wrapper() {
            if (handle_ != 0 && auto_free_) {
                BOOL zero_is_ok = FreeLibrary(handle_);
                (zero_is_ok == 0);
            }
            handle_ = 0;
        }

        bool loaded() const {
            return (handle_ != 0);
        }

        bool failed() const {
            return failed_;
        }

        void* get_fn_addr(const std::string& name) {
            load_if_necessary_();
            if (handle_ != 0) {
                FARPROC addr = GetProcAddress(handle_, name.c_str());
                return addr;
            } else {
                return 0;
            }
        }

    private:

        void load_if_necessary_() {
            if (handle_ == 0 && !failed_) {
                handle_ = LoadLibrary(path_.c_str());
            }
            if (handle_ == 0) {
                failed_ = true;
            }
        }

    private:

        HMODULE     handle_;    //!< The win32 shared library handle.
        std::string path_;      //!< The path to the shared library.
        bool        auto_free_; //!< Whether to free the shared library on destruction.
        bool        failed_;    //!< Whether the shared library has failed to be loaded.

    }; // class shared_lib_wrapper

} // namespace zzheng::sys::detail
} // namespace zzheng::sys
} // namespace zzheng

#endif // !DOXYGEN_SHOULD_SKIP_THIS

#endif // ZZHENG_UTILITY_SHARED_LIB_WIN32_HPP_20080828__


